www.gusucode.com > VC++下的串行数据通信以及八个串口编程实例- > VC++下的串行数据通信以及八个串口编程实例-/第7章 智能安防报警系统/AlertView.cpp

    // AlertView.cpp : implementation of the CAlertView class
//

#include "stdafx.h"
#include "Alert.h"

#include "AlertDoc.h"
#include "AlertView.h"
#include "WinIO.h"
#include "CommSettingDlg.h"
#include "SetParaDlg.h"
#include "LogDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAlertView

IMPLEMENT_DYNCREATE(CAlertView, CFormView)

BEGIN_MESSAGE_MAP(CAlertView, CFormView)
	//{{AFX_MSG_MAP(CAlertView)
	ON_WM_TIMER()
	ON_UPDATE_COMMAND_UI(ID_ALERT_START, OnUpdateAlertStart)
	ON_COMMAND(ID_ALERT_START, OnAlertStart)
	ON_COMMAND(ID_SETTINGS, OnSettings)
	ON_COMMAND(ID_LOG_MANAGE, OnLogManage)
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)
END_MESSAGE_MAP()



/////////////////////////////////////////////////////////////////////////////
// CAlertView construction/destruction

CAlertView::CAlertView()
	: CFormView(CAlertView::IDD)
{
	//{{AFX_DATA_INIT(CAlertView)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	// TODO: add construction code here

}

CAlertView::~CAlertView()
{
}

void CAlertView::DoDataExchange(CDataExchange* pDX)
{
	CFormView::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAlertView)
	DDX_Control(pDX, IDC_LIST_TODAY, m_logList);
	DDX_Control(pDX, IDC_MSCOMM1, m_Comm1);
	DDX_Control(pDX, IDC_MSCOMM2, m_Comm2);
	//}}AFX_DATA_MAP
}

BOOL CAlertView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CFormView::PreCreateWindow(cs);
}

void CAlertView::OnInitialUpdate()
{
	CFormView::OnInitialUpdate();
	GetParentFrame()->RecalcLayout();
	ResizeParentToFit();
	
	m_logList.InsertColumn(0,"布控名称");
	m_logList.InsertColumn(1,"时间");
	m_logList.InsertColumn(2,"动作");

	CRect rect;
	m_logList.GetClientRect(&rect);

	m_logList.SetColumnWidth(0,rect.Width()/5);
	m_logList.SetColumnWidth(1,rect.Width()*2/5);
	m_logList.SetColumnWidth(2,rect.Width()*2/5);

	CTime date=CTime::GetCurrentTime();
	CString strDate=date.Format("%Y-%m-%d");
	CString strSql="select * from log  where date >= #"+strDate+"#";
	m_bstrSQL = strSql.AllocSysString();

	m_pRsLog.CreateInstance(_uuidof(Recordset));	//初始化Recordset指针
	CAlertApp* pApp=(CAlertApp*)::AfxGetApp();
	//adOpenStatic:静态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句
	m_pRsLog->Open(m_bstrSQL,(IDispatch*)pApp->m_pConnection,adOpenStatic,adLockOptimistic,adCmdText); 
	m_cntLog = m_pRsLog->RecordCount;
	ShowLog();					//显示日志表中今日的记录
    m_pRsLog->Close();
	m_pRsLog=NULL;

	initcpara();				//初始化端口

	//启动检测系统
	m_bAction=FALSE;
	m_nTimer = SetTimer(1, 5000, 0);	

}


/////////////////////////////////////////////////////////////////////////////
// CAlertView printing

BOOL CAlertView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CAlertView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CAlertView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

void CAlertView::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/)
{
	// TODO: add customized printing code here
}

/////////////////////////////////////////////////////////////////////////////
// CAlertView diagnostics

#ifdef _DEBUG
void CAlertView::AssertValid() const
{
	CFormView::AssertValid();
}

void CAlertView::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}

CAlertDoc* CAlertView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAlertDoc)));
	return (CAlertDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CAlertView message handlers

void CAlertView::ShowLog()
{
	if(m_pRsLog==NULL)
		return;

	int i=0;
	CString strText;
	_variant_t bfname,date,time,cjname;		//VARIANT数据类型

	m_logList.DeleteAllItems();
	if(!m_pRsLog->RecordCount)
		return;

	m_pRsLog->MoveFirst();
	while(!m_pRsLog->adoEOF)//遍历所有记录
	{ 
//		strText.Format(TEXT("item %d"), i);

		int nItem;
		bfname = m_pRsLog->GetCollect("bfname");//得到字段"bfname"的值
		if(bfname.vt!=VT_NULL)
			nItem=m_logList.InsertItem(0,_bstr_t(bfname));

		date = m_pRsLog->GetCollect("date");	//得到字段"date"的值
		time = m_pRsLog->GetCollect("time");	//得到字段"time"的值
		if(date.vt!=VT_NULL && time.vt!=VT_NULL)
			m_logList.SetItemText(nItem,1,_bstr_t(date)+_bstr_t(" ")+_bstr_t(time));
	
		cjname = m_pRsLog->GetCollect("cjname");//得到字段"cjname"的值
		if(cjname.vt!=VT_NULL)
			m_logList.SetItemText(nItem,2,_bstr_t(cjname));

		m_pRsLog->MoveNext();//转到下一条纪录
		i++;
	}

}

void CAlertView::initcpara()
{
	TRY
	{
		initcom();		//初始化串口
	}
	CATCH(CException,e)
	{
		e->ReportError();
	}
	END_CATCH
	BOOL bResult = InitializeWinIo();	//初始化WinIO库
	if (!bResult)
	{
		::AfxMessageBox("WINIO库初始化失败");
	}
	getLpt();		//从数据库中得到可以使用的并口编号,并赋予数组lptPort	
}

void CAlertView::OnTimer(UINT nIDEvent) 
{
	// TODO: Add your message handler code here and/or call default
	if(nIDEvent==1)
	{
		if(m_bAction==TRUE)
		{
			SpyOn();              //对布防设置进行监控
			updateLog();          //更新日志
		}
	}

	CFormView::OnTimer(nIDEvent);
}

void CAlertView::OnUpdateAlertStart(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->SetCheck(m_bAction);
}

void CAlertView::OnAlertStart() 
{
	// TODO: Add your command handler code here
	m_bAction=!m_bAction;
	//工具栏图标问题未处理
}

//监控子程序:从各监控端口取数据判断触发事件是否发生,并给以处警
void CAlertView::SpyOn()
{
	if(m_lptInbf)
	{
		for(int i=0;i<lptPortArray.GetSize();i++)
		{
			DWORD portVal;
			GetPortVal(lptPortArray[i], &portVal, 1);
			processLook((BYTE)portVal, FALSE);
		}
	}
}

//提取端口内容,判断触发事件的发生,找出对应设置响应,并记录入日志
void CAlertView::processLook(BYTE br, BOOL c)
{
	CString s;
	if(c)
		s = "select * from bufangset where property='串口'";
	else
        s = "select * from bufangset where property='并口'";

	_RecordsetPtr r;
	r.CreateInstance(_uuidof(Recordset));
	CAlertApp* pApp=(CAlertApp*)::AfxGetApp();
	//adOpenStatic:静态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句
	_bstr_t bs=s.AllocSysString();
	r->Open(bs,(IDispatch*)pApp->m_pConnection,adOpenStatic,adLockOptimistic,adCmdText); 
	if(r->RecordCount==0)
		goto finish;
	r->MoveFirst();
	while(!r->adoEOF)
	{
        //若有事件发生,则响应该触发事件
		CString s1,s2;
		_bstr_t bs1,bs2;
		_bstr_t bfname,cjname;
		_RecordsetPtr r1,r2;
		int count;

		BYTE bfcode= BYTE(r->GetCollect("bfcode"));
		bfname= _bstr_t(r->GetCollect("bfname"));
		if(!br || bfcode!= br)
			continue;
		//找出对应处警设置

		r1.CreateInstance(_uuidof(Recordset));
		bs1="select cjname from  bftocj where bfname = '" +bfname +"'";
		r1->Open(bs1,(IDispatch*)pApp->m_pConnection,adOpenStatic,adLockOptimistic,adCmdText);

		cjname=_bstr_t(r1->GetCollect("cjname"));
		CString temp=LPTSTR(cjname);
		count=analystRs(temp);

		//记入日志
		r2.CreateInstance(_uuidof(Recordset));
		s2="select cjname from log";
		bs2=s2.AllocSysString();
		r2->Open(bs2,(IDispatch*)pApp->m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText);

		r2->AddNew();
		r2->PutCollect("bfname",bfname);
		r2->PutCollect("cjname",cjname);
		COleDateTime t=COleDateTime::GetCurrentTime();
		t.Format("%Y-%m-%d");
		r2->PutCollect("date",COleVariant(t));
		t.Format("%H:%M:%S");
		r2->PutCollect("time",COleVariant(t));
		r2->Update();

		r2->Close();
		r1->Close();
		r2=r1=NULL;

		//予以处警响应
		for(int i=0;i<count;i++)
		{
			r1.CreateInstance(_uuidof(Recordset));
			bs1="select * from  chujingset where cjname = '" +strcj[i] +"'";
			r1->Open(bs1,(IDispatch*)pApp->m_pConnection,adOpenStatic,adLockOptimistic,adCmdText);
			while(!r1->adoEOF)
			{
				_bstr_t property=_bstr_t(r1->GetCollect("property"));

				if(property==_bstr_t("串口"))
				{
					if(m_Comm1.GetPortOpen())
					{
						char telnum[20];
						itoa(long(r1->GetCollect("telnumber")),telnum,10);
						char out[100];
						strcpy(out,"ATDT");
						strcat(out,telnum);
						int len=strlen(out);
						out[len]=0x0d;
						out[len+1]=0x0a;
						out[len+2]=0;
						m_Comm1.SetOutput(_variant_t(out));
					}
				}
				if(property==_bstr_t("并口"))
				{
					BOOL res;
					_bstr_t typeact=_bstr_t(r1->GetCollect("typeact"));
					if(typeact==_bstr_t("拨号"))
						res=SetPortVal(long(r1->GetCollect("number")),long(r1->GetCollect("telnumber")),1);	//只写一字节?
					else			//发码
						res=SetPortVal(long(r1->GetCollect("number")),long(r1->GetCollect("infocode")),1);
					if(res==FALSE)
						::AfxMessageBox("WinIO 库未成功安装");
				}
				r1->MoveNext();
			}
			r1->Close();
			r1=NULL;
		}
		r->MoveNext();
	}

finish:
	r->Close();
	r=NULL;
}

//触发器源+事件+处警动作
//日志更新
void CAlertView::updateLog()
{
	m_pRsLog.CreateInstance(_uuidof(Recordset));	//初始化Recordset指针
	CAlertApp* pApp=(CAlertApp*)::AfxGetApp();
	//adOpenStatic:静态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句
	m_pRsLog->Open(m_bstrSQL,(IDispatch*)pApp->m_pConnection,adOpenStatic,adLockOptimistic,adCmdText); 
	if(m_cntLog!=m_pRsLog->RecordCount)
	{
		m_cntLog=m_pRsLog->RecordCount;				//显示日志表中今日的记录
		ShowLog();
	}
    m_pRsLog->Close();
	m_pRsLog=NULL;
}


int CAlertView::analystRs(CString cjname)
{
	int count=0;	//count:纪录获取的字符串个数
	strcj.RemoveAll();
	strcj.Add("");
	for(int i=0;i<cjname.GetLength();i++)
	{
		if(cjname[i]!='@')
			strcj[count]+=cjname[i];
		else
		{
			count+=1;
			strcj.Add("");
		}
	}
	if(strcj[count]=="")
	{
		strcj.RemoveAt(count);
		count--;
	}
	return count+1;
}

//初始化COM口
void CAlertView::initcom()
{
	//初始化处警拨号使用的com口(控件:mscomm1)
	_RecordsetPtr r;
	r.CreateInstance(_uuidof(Recordset));
	CString s= "select distinct number from chujingset where property='串口'";
	_bstr_t bs=s.AllocSysString();
	CAlertApp* pApp=(CAlertApp*)::AfxGetApp();
	//adOpenStatic:静态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句
	r->Open(bs,(IDispatch*)pApp->m_pConnection,adOpenStatic,adLockOptimistic,adCmdText); 
	CString strcom,commSetting,commHandShaking;
	int commport = (BYTE)r->GetCollect("number");		//处警表里面使用的com口端口号
	itoa(commport,strcom.GetBuffer(10),10);
	strcom.ReleaseBuffer();
	r->Close();
	r=NULL;
	
	commSetting = GetSetting(CString("PortSetting\\Com")+strcom+"\\", "commSetting");
	commHandShaking = GetSetting(CString("PortSetting\\Com")+strcom+"\\", "commHandshaking");
	while((commSetting=="")||(commHandShaking==""))
	{
		CCommSettingDlg dlg;
		dlg.m_strChoose=CString("串口")+strcom;
		dlg.DoModal();
		commSetting = GetSetting(CString("PortSetting\\Com")+strcom+"\\", "commSetting");
		commHandShaking = GetSetting(CString("PortSetting\\Com")+strcom+"\\", "commHandshaking");
	}
	m_Comm1.SetCommPort(commport);
	long shakehand=atol(commHandShaking.GetBuffer(50));
	commHandShaking.ReleaseBuffer();
	m_Comm1.SetSettings(commSetting);
	m_Comm1.SetHandshaking(shakehand);
	TRY
	{
		m_Comm1.SetPortOpen(TRUE);
	}
	CATCH(CException,e)
	{
		e->ReportError();
	}
	END_CATCH
	//如果布防设置中使用到com口的话,则初始化该com口
	//控件:mscomm2
	r.CreateInstance(_uuidof(Recordset));
	s="select distinct number from bufangset where property='串口'";
	bs=s.AllocSysString();
	r->Open(bs,(IDispatch*)pApp->m_pConnection,adOpenStatic,adLockOptimistic,adCmdText);
	commport = (BYTE)r->GetCollect("number");		//布防表里使用的com口端口号
	itoa(commport,strcom.GetBuffer(10),10);
	strcom.ReleaseBuffer();
	if(r->RecordCount==1)
	{
		m_comInbf=TRUE;
		
		commSetting = GetSetting(CString("PortSetting\\Com")+strcom+"\\", "commSetting");
		commHandShaking = GetSetting(CString("PortSetting\\Com")+strcom+"\\", "commHandshaking");
		while((commSetting=="")||(commHandShaking==""))
		{
			CCommSettingDlg dlg;
			dlg.m_strChoose=CString("串口")+strcom;
			dlg.DoModal();
			commSetting = GetSetting(CString("PortSetting\\Com")+strcom+"\\", "commSetting");
			commHandShaking = GetSetting(CString("PortSetting\\Com")+strcom+"\\", "commHandshaking");
		}
		m_Comm2.SetCommPort(commport);
		shakehand=atol(commHandShaking.GetBuffer(50));
		commHandShaking.ReleaseBuffer();
		m_Comm2.SetSettings(commSetting);
		m_Comm2.SetHandshaking(shakehand);
		m_Comm2.SetInputMode(1);
		m_Comm2.SetPortOpen(TRUE);
	}
	else
		m_comInbf=FALSE;	
	r->Close();
	r=NULL;
}

void CAlertView::getLpt()
{
	_RecordsetPtr r;
	r.CreateInstance(_uuidof(Recordset));
	CString s="select distinct number from bufangset where property='并口' and promote=true";
	_bstr_t bs=s.AllocSysString();
	CAlertApp* pApp=(CAlertApp*)::AfxGetApp();
	r->Open(bs,(IDispatch*)pApp->m_pConnection,adOpenStatic, adLockOptimistic, adCmdText);
	//若在布防设置表中select出的并口项数量为零则判断系统不使用并口,反之使用
	lptPortArray.RemoveAll();
	if(r->RecordCount==0)
		m_lptInbf=FALSE;
	else
	{
		//若有并口则开一个并口端口数组,并给数组赋值
		m_lptInbf=TRUE;
		TRY
		{
			r->MoveFirst();
			for(int i=0; i<r->RecordCount; i++)
			{
				lptPortArray.Add((long)r->GetCollect("Number"));
				r->MoveNext();
			}
		}
		CATCH(CException,e)
		{
			e->ReportError();
		}
		END_CATCH
	}
	r->Close();
	r=NULL;
}

BEGIN_EVENTSINK_MAP(CAlertView, CFormView)
    //{{AFX_EVENTSINK_MAP(CAlertView)
	ON_EVENT(CAlertView, IDC_MSCOMM2, 1 /* OnComm */, OnOnCommMscomm2, VTS_NONE)
	//}}AFX_EVENTSINK_MAP
END_EVENTSINK_MAP()

void CAlertView::OnOnCommMscomm2() 
{
	// TODO: Add your control notification handler code here
	if(m_Comm2.GetCommEvent()==2)     //事件值为2表示接收缓冲区内有字符
	{
		CString str=VARIANT2str(m_Comm2.GetInput());
		for(int i=0; i<str.GetLength();i++)
			processLook(str[i],TRUE);
	}
}

void CAlertView::OnSettings() 
{
	// TODO: Add your command handler code here
	m_bAction=FALSE;
	CSetParaDlg dlg;
	dlg.DoModal();
//	m_bAction=TRUE;
}

void CAlertView::OnLogManage() 
{
	// TODO: Add your command handler code here
	CLogDlg dlg(this);
	dlg.DoModal();
}